package com.authine.cloudpivot.ext.service.goldentax.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.ext.Enum.GoldenTaxStatus;
import com.authine.cloudpivot.ext.Enum.InvoiceBusinessType;
import com.authine.cloudpivot.ext.Enum.InvoiceStatus;
import com.authine.cloudpivot.ext.Enum.TradeOrderType;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.finance.GoldenTaxUpdateModel;
import com.authine.cloudpivot.ext.dto.model.golden.GoldenTax;
import com.authine.cloudpivot.ext.dto.model.golden.GoldenTaxDetail;
import com.authine.cloudpivot.ext.dto.model.invoice.InvoiceApply;
import com.authine.cloudpivot.ext.dto.model.invoice.InvoiceDetail;
import com.authine.cloudpivot.ext.service.goldentax.GoldenTaxService;
import com.authine.cloudpivot.ext.utils.BoServiceUtils;
import com.authine.cloudpivot.ext.utils.JdbcTemplateUtils;
import com.authine.cloudpivot.ext.utils.RegexUtils;
import com.authine.cloudpivot.ext.utils.TaxRateUtils;
import com.authine.common.json.JsonUtils;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Slf4j
public class GoldenTaxServiceImpl implements GoldenTaxService {

    /**
     * 逻辑删除金税开票记录和开票明细
     * @param ids
     */
    @Override
    public void delete(List<String> ids){
        //删除金税开票记录
        JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX)
                .putFieldAndVal("deleted",1)
                .eq("deleted",0)
                .in("id", ids)
                .update();

        //删除金税开票明细记录
        JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX_DETAIL)
                .putFieldAndVal("deleted", 1)
                .eq("deleted",0)
                .in("golden_tax_id", ids)
                .update();
    }

    /**
     * 获取金税开票完成的数据
     * @param goldenTaxIds
     * @return
     */
    @Override
    public List<GoldenTax> listDone(List<String> goldenTaxIds){
        List<GoldenTax> goldenTaxList = JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX).selectField(" * ")
                .eq("deleted", "0")
                .eq("statuss", "Done")
                .in("id", goldenTaxIds)
                .queryForPOJOList(GoldenTax.class);
        if (CollectionUtils.isEmpty(goldenTaxList)) {
            return goldenTaxList;
        }
        List<GoldenTax> collect = goldenTaxList.stream().filter(t -> t.getPrice_amount().compareTo(BigDecimal.ZERO) != -1).collect(Collectors.toList());
        collect.addAll(correctWrongData(goldenTaxList.stream().filter(t -> t.getPrice_amount().compareTo(BigDecimal.ZERO) == -1).collect(Collectors.toList())));
        return collect;
    }

    /**
     *  创建金税信息
     * @param invoiceApply
     * @return 金税信息记录ID
     */
    @Override
    public String generateGoldenTax(InvoiceApply invoiceApply){
        if (!PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(invoiceApply.getSale_organization_id().getId())
                || !InvoiceStatus.DrawerConfirming.name().equals(invoiceApply.getStatuss())) {
            return null;
        }
        List<InvoiceDetail> details = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL).selectField(" * ").eq("invoice_apply_id", invoiceApply.getId())
                .queryForPOJOList(InvoiceDetail.class);
        details = details.stream().sorted(Comparator.comparing(InvoiceDetail::getTrade_id).reversed()).collect(Collectors.toList());
        Assert.isTrue(!CollectionUtils.isEmpty(details), "未查到发票明细");

        GoldenTax goldenTax = null;
        if (InvoiceBusinessType.Product.name().equals(invoiceApply.getBusiness_type())) {
            List<String> contractServiceTradeIds = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField(" id ")
                    .eq("business_type", TradeOrderType.Agent)
                    .eq("deleted", 0)
                    .in("id", details.stream().map(InvoiceDetail::getTrade_id).collect(Collectors.toList()))
                    .like("summary", PlatformConst.SERVICE_INVOICE_NAME)
                    .queryForList(String.class);
            List<GoldenTaxDetail> goldenTaxDetailList = new ArrayList<>();
            for (InvoiceDetail invoiceDetail : details){
                if (contractServiceTradeIds.contains(invoiceDetail.getTrade_id()) && StringUtils.isBlank(invoiceDetail.getGolden_tax())) {
                    //invoiceDetail.setGolden_tax(PlatformConst.SERVICE_INVOICE_GOLDEN_TAX);
                    JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL).putFieldAndVal("golden_tax", PlatformConst.SERVICE_INVOICE_GOLDEN_TAX)
                            .eq("id", invoiceDetail.getId()).update();
                }
                GoldenTaxDetail goldenTaxDetail = GoldenTaxDetail.builder()
                        .name(invoiceDetail.getName().trim())
                        .model_spec(invoiceDetail.getModel_spec().trim())
                        .unit(invoiceDetail.getUnit().trim())
                        .quantity(invoiceDetail.getQuantity())
                        .gross_price(invoiceDetail.getGross_price())
                        .amount(invoiceDetail.getAmount())
                        .tax_rate(invoiceDetail.getTax_rate())
                        .tax(invoiceDetail.getTax())
                        .golden_tax(invoiceDetail.getGolden_tax())
                        .build();
                goldenTaxDetailList.add(goldenTaxDetail);
            }
            goldenTax = GoldenTax.builder()
                    .purchase_number(invoiceApply.getPurchase_number())
                    .purchase_name(invoiceApply.getPurchase_name())
                    .purchase_address_phone(invoiceApply.getPurchase_address() + " " + invoiceApply.getPurchase_phone())
                    .purchase_bank_account(invoiceApply.getPurchase_bank() + " " + invoiceApply.getPurchase_account())
                    .apply_member_name(invoiceApply.getApply_member_name())
                    .apply_member_id(invoiceApply.getApply_member_id())
                    .memo(invoiceApply.getMemo())
                    .goldenTaxDetailList(goldenTaxDetailList)
                    .total(invoiceApply.getTotal())
                    .build();

        } else if (InvoiceBusinessType.Service.name().equals(invoiceApply.getBusiness_type())) {
            //根据含税价格计算税前价格
            BigDecimal priceAmount = TaxRateUtils.calculateTaxBefore(invoiceApply.getTotal(), PlatformConst.PLATTAXRATE);
            BigDecimal taxAmount = invoiceApply.getTotal().subtract(priceAmount);
            GoldenTaxDetail goldenTaxDetail = GoldenTaxDetail.builder()
                    .golden_tax(PlatformConst.SERVICE_INVOICE_GOLDEN_TAX)
                    .name(PlatformConst.SERVICE_INVOICE_NAME)
                    .quantity(new BigDecimal("1")).gross_price(invoiceApply.getTotal()).amount(priceAmount)
                    .tax_rate(PlatformConst.PLATRATE).tax(taxAmount).build();
            goldenTaxDetail.setIfService(true);

            goldenTax = GoldenTax.builder()
                    .purchase_number(invoiceApply.getPurchase_number())
                    .purchase_name(invoiceApply.getPurchase_name())
                    .purchase_address_phone(invoiceApply.getPurchase_address() + " " + invoiceApply.getPurchase_phone())
                    .purchase_bank_account(invoiceApply.getPurchase_bank() + " " + invoiceApply.getPurchase_account())
                    .apply_member_name(invoiceApply.getApply_member_name())
                    .apply_member_id(invoiceApply.getApply_member_id())
                    .memo(invoiceApply.getMemo())
                    .goldenTaxDetailList(Collections.singletonList(goldenTaxDetail))
                    .total(invoiceApply.getTotal()).build();
        }
        return this.create(goldenTax);

    }

    @Override
    public void updateGoldenTax(Collection<GoldenTaxUpdateModel> goldenTaxUpdateModels) {
        log.info("==========修改金税明细编码{}=============", JSON.toJSONString(goldenTaxUpdateModels));
        if (CollectionUtils.isEmpty(goldenTaxUpdateModels)) {
            return;
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("GoldenTaxService.updateGoldenTax()新版财务修改金税编码信息");

        List<String> goldenTaxIds = goldenTaxUpdateModels.stream().map(GoldenTaxUpdateModel::getGoldenTaxId).collect(Collectors.toList());

        List<GoldenTaxDetail> goldenTaxDetailList = JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX_DETAIL).selectField("*")
                .in("golden_tax_id", goldenTaxIds)
                .queryForPOJOList(GoldenTaxDetail.class);
        if (CollectionUtils.isEmpty(goldenTaxDetailList)) {
            return;
        }

        for (GoldenTaxDetail goldenTaxDetail : goldenTaxDetailList) {
            Predicate<GoldenTaxUpdateModel> modelPredicate = t -> {
                if (t.getIfUpdate()) {
                    return false;
                } else if (!goldenTaxDetail.getGolden_tax_id().equals(t.getGoldenTaxId())) {
                    return false;
                } else if (RegexUtils.notNull(t.getOldGoldenTax()) && !t.getOldGoldenTax().equals(goldenTaxDetail.getGolden_tax())) {
                    return false;
                } else if (!goldenTaxDetail.getName().equals(t.getName())) {
                    return false;
                } else if (!goldenTaxDetail.getModel_spec().equals(t.getModelSpec())) {
                    return false;
                } else if (!goldenTaxDetail.getUnit().equals(t.getUnit())) {
                    return false;
                } else if (goldenTaxDetail.getQuantity().compareTo(t.getQuantity()) != 0) {
                    return false;
                } else {
                    return goldenTaxDetail.getGross_price().compareTo(t.getGrossPrice()) == 0;
                }
            };

            List<GoldenTaxUpdateModel> goldenTaxUpdateModelList = goldenTaxUpdateModels.stream().filter(modelPredicate).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(goldenTaxUpdateModelList)) {
                continue;
            }

            GoldenTaxUpdateModel goldenTaxUpdateModel = goldenTaxUpdateModelList.get(0);
            goldenTaxUpdateModel.setIfUpdate(true);

            goldenTaxDetail.setGolden_tax(goldenTaxUpdateModel.getGoldenTax());
            BoServiceUtils.updateMainBo(ModelConst.T_GOLDEN_TAX_DETAIL, BeanUtil.beanToMap(goldenTaxDetail));

        }
        log.info("==========修改金税明细编码成功=============");
    }

    public String create(GoldenTax goldenTax){
        log.info("==========创建金税发票单{}=============", JSON.toJSONString(goldenTax));
        boolean requiredVerify = StringUtils.isBlank(goldenTax.getPurchase_name())
                || StringUtils.isBlank(goldenTax.getPurchase_number())
                || StringUtils.isBlank(goldenTax.getPurchase_address_phone())
                || StringUtils.isBlank(goldenTax.getPurchase_bank_account())
                || StringUtils.isBlank(goldenTax.getApply_member_name())
                || null == goldenTax.getTotal()
                || null == goldenTax.getApply_member_id();
        Assert.isTrue(!requiredVerify, "金税发票单必填项不能为空");
        Assert.isTrue(!CollectionUtils.isEmpty(goldenTax.getGoldenTaxDetailList()),"金税发票明细列表不能为空");

        goldenTax.setDiscount(BigDecimal.ZERO).setStatuss(GoldenTaxStatus.DrawerConfirming.name());
        SingleResponse<BO> response = BoServiceUtils.createBo(ModelConst.T_GOLDEN_TAX, Collections.singletonList(BeanUtil.beanToMap(goldenTax)));
        Assert.isTrue(response.isSuccess(),"金税发票明细新增失败");
        goldenTax.setId(response.getData().getBizObjectId());

        log.info(JSON.toJSONString(response.getData().getData()));

        for (GoldenTaxDetail goldenTaxDetail : goldenTax.getGoldenTaxDetailList()) {
            requiredVerify = StringUtils.isBlank(goldenTaxDetail.getName())
                    || null == goldenTaxDetail.getQuantity()
                    || null == goldenTaxDetail.getGross_price()
                    || null == goldenTaxDetail.getAmount()
                    || null == goldenTaxDetail.getTax_rate()
                    || null == goldenTaxDetail.getTax();

            Assert.isTrue(!requiredVerify, "金税发票单明细必填项不能为空");

            if (!goldenTaxDetail.getIfService()) {
                BigDecimal verifyTotal = goldenTaxDetail.getQuantity().multiply(goldenTaxDetail.getGross_price()).setScale(2,RoundingMode.CEILING);
                BigDecimal total = goldenTaxDetail.getAmount().add(goldenTaxDetail.getTax()).setScale(2, RoundingMode.CEILING);
                Assert.isTrue(verifyTotal.compareTo(total) == 0, "含税单价*数量不等于含税总金额");
            } else {
                goldenTaxDetail.setTax_rate(PlatformConst.PLATTAXRATE);
            }

            goldenTaxDetail.setGolden_tax_id(goldenTax.getId());
            goldenTaxDetail.setIs_tax(1).setUntaxed_discount(BigDecimal.ZERO).setDiscount_tax(BigDecimal.ZERO);
            SingleResponse<BO> result = BoServiceUtils.createBo(ModelConst.T_GOLDEN_TAX_DETAIL, Collections.singletonList(BeanUtil.beanToMap(goldenTaxDetail)));
            Assert.isTrue(result.isSuccess(),"金税发票明细新增失败");
        }
        return goldenTax.getId();
    }


    /**
     * 根据t_finance_invoice 里的正确蓝票重新回写由于金税接口会发生回写红字发票的错误回写
     */
    public List<GoldenTax> correctWrongData(List<GoldenTax> errorData){
        if (CollectionUtils.isEmpty(errorData)) {
            return Collections.emptyList();
        }
        List<GoldenTax> results = new ArrayList<>();
        String querySql = "select invoice_time invoiceTime,code,number,drawer,amount,tax_payable taxPayable from " + ModelConst.T_FINANCE_INVOICE + " where invoice_apply_id =:invoiceApplyId and amount>0 ";
        MapBuilder<String, Object> mapBuilder = MapBuilder.create(new HashMap<>());
        for (GoldenTax goldenTax : errorData){
            mapBuilder.map().clear();

            mapBuilder.put("invoiceApplyId", goldenTax.getId());
            List<Map<String, Object>> resultList = JdbcTemplateUtils.queryForList(querySql, mapBuilder.build());
            if (CollectionUtils.isEmpty(resultList)) {
                continue;
            }
            Map<String, Object> map = resultList.get(0);
            mapBuilder.map().clear();
            mapBuilder.put("id", goldenTax.getId())
                    .put("code", map.get("code"))
                    .put("number",map.get("number"))
                    .put("drawer", map.get("drawer"))
                    .put("price_amount", map.get("amount"))
                    .put("tax_amount", map.get("taxPayable"))
                    .put("invoice_time", map.get("invoiceTime"));

            int id = JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX)
                    .putFieldAndVal(mapBuilder.build())
                    .eq("id", goldenTax.getId())
                    .update();
            if(id == 1){
                goldenTax.setInvoice_time(map.get("invoiceTime")==null ? null : (Date)map.get("invoiceTime"))
                        .setCode(map.get("code")==null ? "" : map.get("code").toString())
                        .setNumber(map.get("number")==null ? "" : map.get("number").toString())
                        .setDrawer(map.get("drawer")==null ? "" : map.get("drawer").toString())
                        .setPrice_amount(map.get("amount")==null ? null : new BigDecimal(map.get("amount").toString()))
                        .setTax_amount(map.get("taxPayable")==null ? null : new BigDecimal(map.get("taxPayable").toString()));
                results.add(goldenTax);
            }

        }
        return results;
    }


}
